package com.kede.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.kede.app.domain.ZhiAction;
import com.kede.app.domain.ZhiCategory;
import com.kede.app.domain.ZhiImgs;
import com.kede.app.po.ModifyCardGroupPo;
import com.kede.app.repository.ZhiActionRepository;
import com.kede.app.repository.ZhiCategoryRepository;
import com.kede.app.repository.ZhiImgsRepository;
import com.kede.app.service.ZhiCategoryService;
import com.kede.app.service.dto.ZhiCategoryDto;
import com.kede.app.service.dto.ZhiCategoryQueryCriteria;
import com.kede.app.service.mapstruct.ZhiCategoryMapper;
import com.kede.utils.FileUtil;
import com.kede.utils.PageUtil;
import com.kede.utils.QueryHelp;
import com.kede.utils.ValidationUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
* @description 服务实现
* @author Pr.li
* @date 2023-07-02
**/
@Service
@RequiredArgsConstructor
public class ZhiCategoryServiceImpl implements ZhiCategoryService {

    private final ZhiCategoryRepository zhiCategoryRepository;
    private final ZhiCategoryMapper zhiCategoryMapper;

    private final ZhiActionRepository zhiActionRepository;
    private final ZhiImgsRepository zhiImgsRepository;

    @Override
    public Map<String,Object> queryAll(ZhiCategoryQueryCriteria criteria, Pageable pageable){
        Page<ZhiCategory> page = zhiCategoryRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(zhiCategoryMapper::toDto));
    }

    @Override
    public List<ZhiCategoryDto> queryAll(ZhiCategoryQueryCriteria criteria){
        return zhiCategoryMapper.toDto(zhiCategoryRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public ZhiCategoryDto findById(Integer id) {
        ZhiCategory zhiCategory = zhiCategoryRepository.findById(id).orElseGet(ZhiCategory::new);
        ValidationUtil.isNull(zhiCategory.getId(),"ZhiCategory","id",id);
        return zhiCategoryMapper.toDto(zhiCategory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ZhiCategoryDto create(ZhiCategory resources) {
        return zhiCategoryMapper.toDto(zhiCategoryRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ZhiCategory resources) {
        ZhiCategory zhiCategory = zhiCategoryRepository.findById(resources.getId()).orElseGet(ZhiCategory::new);
        ValidationUtil.isNull( zhiCategory.getId(),"ZhiCategory","id",resources.getId());
        zhiCategory.copy(resources);
        zhiCategoryRepository.save(zhiCategory);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            zhiCategoryRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<ZhiCategoryDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ZhiCategoryDto zhiCategory : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put(" pid",  zhiCategory.getPid());
            map.put("品类名称", zhiCategory.getName());
            map.put("默认用户价格", zhiCategory.getDefaultUserMoney());
            map.put("默认门店价格", zhiCategory.getDefaultStoreMoney());
            map.put("默认区代价格", zhiCategory.getDefaultQuMoney());
            map.put("默认市代价格", zhiCategory.getDefaultShiMoney());
            map.put(" createTime",  zhiCategory.getCreateTime());
            map.put(" updateTime",  zhiCategory.getUpdateTime());
            map.put(" createBy",  zhiCategory.getCreateBy());
            map.put(" updateBy",  zhiCategory.getUpdateBy());
            map.put("所属组", zhiCategory.getGroup());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<ZhiCategory> getChildsById(Integer id) {
        List<ZhiCategory> allByPid = zhiCategoryRepository.findAllByPid(id);
        allByPid.forEach(zhiCategory -> {
            zhiCategory.setZhiActionList(zhiActionRepository.findAllByNodeId(zhiCategory.getId()));
            zhiCategory.setImgs(zhiImgsRepository.findByNodeId(zhiCategory.getId()));
        });
        return allByPid;
    }

    @Override
    public ZhiCategory getOneZhiCateInfoById(Integer id){
        Optional<ZhiCategory> byId = zhiCategoryRepository.findById(id);
        ZhiCategory zhiCategory = new ZhiCategory();
        if (byId.isPresent()) {
            ZhiCategory src = byId.get();
            BeanUtil.copyProperties(src,zhiCategory);
            paddingCate(src,zhiCategory);
        }
        return zhiCategory;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean modifyCardGroup(ModifyCardGroupPo modifyCardGroupPo) {
        for (Integer id : modifyCardGroupPo.getIds()) {
            ZhiCategory byId = zhiCategoryRepository.getById(id);
            byId.setGroup(modifyCardGroupPo.getGroupName());
            zhiCategoryRepository.save(byId);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean delCard(Integer[] ids) {
        List<ZhiCategory> all  = new ArrayList<>();
        for (Integer id : ids) {
            all.add(zhiCategoryRepository.getById(id));
            all.addAll(getCurAndChildCateIds(id));
        }
        zhiCategoryRepository.deleteAll(all);
        return true;
    }

    private List<ZhiCategory> getCurAndChildCateIds(Integer id){
        List<ZhiCategory> all  = new ArrayList<>();
        List<ZhiCategory> allByPid = zhiCategoryRepository.findAllByPid(id);
        for (ZhiCategory zhiCategory : allByPid) {
            all.add(zhiCategory);
            List<ZhiCategory> allByPidchild = zhiCategoryRepository.findAllByPid(id);
            if(allByPidchild != null && allByPidchild.size() > 0){
               all.addAll(getCurAndChildCateIds(zhiCategory.getId()));
            }
        }
        return all;
    }


    private static BigDecimal ZERO = new BigDecimal("0");
    private static BigDecimal AsNUll = new BigDecimal("-1");

    private boolean canDeepCate(BigDecimal target){
        return target == null || target.compareTo(AsNUll) == 0;
    }
    /**
     * 通过递归循环填充 target完整属性
     * @param src
     * @param target
     */
    private void paddingCate(ZhiCategory src,ZhiCategory target){
        boolean goParent = false;
        if(canDeepCate(target.getDefaultQuMoney())){
            if(!canDeepCate(src.getDefaultQuMoney())){
                target.setDefaultQuMoney(src.getDefaultQuMoney());
            }else{
                goParent = true;
            }
        }
        if(canDeepCate(target.getDefaultShiMoney()) ){
            if(!canDeepCate(src.getDefaultShiMoney())){
                target.setDefaultShiMoney(src.getDefaultShiMoney());
            }else{
                goParent = true;
            }
        }
        if(canDeepCate(target.getDefaultStoreMoney())){
            if(!canDeepCate(src.getDefaultStoreMoney())){
                target.setDefaultStoreMoney(src.getDefaultStoreMoney());
            }else{
                goParent = true;
            }
        }
        if(canDeepCate(target.getDefaultUserMoney()) ){
            if(!canDeepCate(src.getDefaultUserMoney())){
                target.setDefaultUserMoney(src.getDefaultUserMoney());
            }else{
                goParent = true;
            }
        }
        if(canDeepCate(target.getDefaultUserDebi()) ){
            if(!canDeepCate(src.getDefaultUserDebi())){
                target.setDefaultUserDebi(src.getDefaultUserDebi());
            }else{
                goParent = true;
            }
        }
        if(target.getZhiActionList() == null ){
            List<ZhiAction> action = zhiActionRepository.findAllByNodeId(src.getId());
            if(action !=null && action.size() > 0){
                target.setZhiActionList(action);
            }else{
                goParent = true;
            }
        }
        if(target.getImgs() == null ){
            ZhiImgs zhiImgs = zhiImgsRepository.findByNodeId(src.getId());
            if(zhiImgs != null){
                target.setImgs(zhiImgs);
            }else{
                goParent = true;
            }
        }
        if(goParent){
            if(src.getPid().equals(0)){
                return;
            }
            ZhiCategory byId = zhiCategoryRepository.getById(src.getPid());
            if(byId != null){
                paddingCate(byId,target);
            }
        }
    }
}